package team.seekers.hula.island.island.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import team.seekers.hula.common.entity.PageResult;
import team.seekers.hula.common.entity.enums.IslandTypeEnum;
import team.seekers.hula.common.utils.BaseConvertUtils;
import team.seekers.hula.course.course.service.CourseService;
import team.seekers.hula.island.island.entity.dto.*;
import team.seekers.hula.island.island.entity.vo.IslandManageInfoVO;
import team.seekers.hula.island.island.entity.vo.IslandPageListVO;
import team.seekers.hula.island.islandUser.entity.dto.IslandEvaluationReqListDTO;
import team.seekers.hula.island.islandUser.entity.dto.IslandUserListDTO;
import team.seekers.hula.island.islandUser.entity.vo.IslandEvaluationListVO;
import team.seekers.hula.island.islandUser.entity.vo.IslandUserListVO;
import team.seekers.hula.island.islandUser.service.IslandUserService;
import team.seekers.hula.island.post.service.IslandPostService;
import team.seekers.hula.auth.service.MindUtils;
import team.seekers.hula.island.island.dao.IslandDao;
import team.seekers.hula.island.islandUser.dao.IslandUserDao;
import team.seekers.hula.island.islandUser.entity.dao.IslandUserDO;
import team.seekers.hula.island.island.entity.dao.IslandDO;
import team.seekers.hula.island.island.entity.vo.IslandInfoVO;
import team.seekers.hula.island.island.entity.vo.IslandListVO;
import team.seekers.hula.user.user.entity.dao.UserDO;
import team.seekers.hula.user.user.entity.dto.UserInfoDTO;
import team.seekers.hula.user.user.service.UserService;

import java.util.*;

/**
 * @author ekin
 * @Description GOOD
 * @mood happy
 */
@Service
public class IslandService{

    private static Integer MARK_MAX_COUNT = 5;

    @Autowired
    private IslandDao islandDao;

    @Autowired
    private IslandUserDao islandUserDao;

    @Autowired
    private IslandUserService islandUserService;

    @Autowired
    @Lazy
    private IslandPostService islandPostService;

    @Autowired
    private UserService userService;

    @Autowired
    private CourseService courseService;

    public String add(IslandAddDTO addVO) {
        IslandDO islandDO = new IslandDO();
        BeanUtils.copyProperties(addVO, islandDO);
        islandDO.setUserId(MindUtils.getUserId());
        islandDao.save(islandDO);

        IslandUserDO islandUserDO = new IslandUserDO();
        islandUserDO.setIslandId(islandDO.getId());
        islandUserDO.setUserId(addVO.getUserId());
        islandUserDO.setRole(2);
        islandUserDao.save(islandUserDO);

        return islandDO.getId();
    }

    public List<IslandInfoVO> queryIslands() {
        List<IslandDO> lists = islandDao.list();
        ArrayList<IslandInfoVO> listVOS = new ArrayList<>();
        for (IslandDO list : lists) {
            IslandInfoVO islandInfoVO = new IslandInfoVO();
            BeanUtils.copyProperties(list, islandInfoVO);
            listVOS.add(islandInfoVO);
        }
        return listVOS;
    }

    public List<IslandListVO> listMyAdmin(String userId) {
        List<IslandDO> islandDOS = islandDao.lambdaQuery().eq(IslandDO::getUserId, userId).list();

        ArrayList<IslandListVO> islandListVOS = new ArrayList<>();
        for (IslandDO islandDO : islandDOS) {
            IslandListVO islandListVO = new IslandListVO();
            BeanUtils.copyProperties(islandDO,islandListVO);
            islandListVO.setType(islandDO.getType().getType());
            islandListVOS.add(islandListVO);
        }

        return islandListVOS;
    }



    public Integer markCount(MarkCountDTO markCountDTO) {
        IslandUserDO one = islandUserDao.getOne(new QueryWrapper<IslandUserDO>().eq("island_id", markCountDTO.getIslandId()).eq("user_id", markCountDTO.getUserId()));

        return MARK_MAX_COUNT - one.getCount();
    }

    public IslandInfoVO info(String islandId) {
        IslandDO islandDO = islandDao.getById(islandId);
        IslandInfoVO islandInfoVO = new IslandInfoVO();
        BeanUtils.copyProperties(islandDO,islandInfoVO);



        islandInfoVO.setUserCount(islandUserService.countBuy(islandDO.getId()));


        islandInfoVO.setThreeUserAvatar(islandUserService.getThreeUserAvatar(islandId));

        islandInfoVO.setPostCount(islandPostService.countByIslandId(islandDO.getId()));

        islandInfoVO.setCourses(courseService.getCourseBasicInfoVOList(BaseConvertUtils.stringToList(islandDO.getCourseIds())));

        islandInfoVO.setType(islandDO.getType().getType());

        if(MindUtils.isLogin()){
            islandInfoVO.setIsBuy(islandUserService.isBuy(islandId,MindUtils.getUserId()));
            islandInfoVO.setIsFixed(islandUserService.isFixed(islandId,MindUtils.getUserId()));
            islandInfoVO.setUserInfo(userService.getFollowInfoVO(islandDO.getUserId(),MindUtils.getUserId()));
        }else{
            islandInfoVO.setUserInfo(userService.getFollowInfoVO(islandDO.getUserId(),null));
        }

        return islandInfoVO;
    }

    public List<IslandListVO> listAdmin(IslandListDTO islandListDTO) {
        QueryWrapper<IslandDO> wrapper = new QueryWrapper<>();
        List<IslandDO> lists = islandDao.list(wrapper.eq("user_id", islandListDTO.getUserId()));
        ArrayList<IslandListVO> listVOS = new ArrayList<>();
        for (IslandDO list : lists) {
            IslandListVO islandListVO = new IslandListVO();
            BeanUtils.copyProperties(list, islandListVO);
            listVOS.add(islandListVO);
        }
        return listVOS;
    }

    public Integer getTypeById(String islandId) {
        return islandDao.lambdaQuery().select(IslandDO::getType).eq(IslandDO::getId,islandId).one().getType().getType();
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateIsland(IslandUpdateDTO reqDTO) {
        IslandDO islandDO = new IslandDO();
        BeanUtils.copyProperties(reqDTO,islandDO);
        islandDO.setType(IslandTypeEnum.getByType(reqDTO.getType()));
        islandDao.updateById(islandDO);
    }

    public IslandManageInfoVO queryManageInfoById(String islandId) {
        IslandDO islandDO = islandDao.getById(islandId);
        IslandManageInfoVO islandManageInfoVO = new IslandManageInfoVO();
        BeanUtils.copyProperties(islandDO, islandManageInfoVO);

        // 查询用户情况
        islandManageInfoVO.setUserCount(islandUserService.countBuy(islandManageInfoVO.getId()));
        islandManageInfoVO.setFixedCount(islandUserService.countFixed(islandManageInfoVO.getId()));


        return islandManageInfoVO;
    }

    public List<IslandListVO> listFixed() {
        // 获取常驻
        List<String> islandIds =  islandUserService.getFixedIslandIds(MindUtils.getUserId());
        if(islandIds == null || islandIds.isEmpty()){
            return new ArrayList<>();
        }else {
            List<IslandDO> islandDOList = islandDao.lambdaQuery().in(IslandDO::getId, islandIds).list();
            return IslandDO.DOListToVOList(islandDOList);
        }
    }

    public List<IslandListVO> listPush() {

        // TODO 获取推荐
        LambdaQueryChainWrapper<IslandDO> lambdaQuery = islandDao.lambdaQuery();
        IslandUserListDTO islandUserListDTO = new IslandUserListDTO();
        if(MindUtils.isLogin()){
            islandUserListDTO.setUserId(MindUtils.getUserId());
            Map<String, IslandUserListVO> userMap = islandUserService.mapByUserIdAndIslandIds(islandUserListDTO);

            ArrayList<String> joinedIslandIds = new ArrayList<>(userMap.keySet());
            if(!joinedIslandIds.isEmpty()){
                lambdaQuery.notIn(IslandDO::getId,joinedIslandIds);
            }
        }
        return IslandDO.DOListToVOList(lambdaQuery.list());
    }

    public PageResult<IslandListVO> page(IslandPageDTO islandPageDTO) {
        LambdaQueryChainWrapper<IslandDO> lambdaQuery = islandDao.lambdaQuery();
        if(StringUtils.isNotBlank(islandPageDTO.getName())){
            lambdaQuery.like(IslandDO::getName,islandPageDTO.getName());
        }
        Map<String, IslandUserListVO> map = new HashMap<>();
        if(StringUtils.isNotBlank(islandPageDTO.getUserId())){
            IslandUserListDTO islandUserListDTO = new IslandUserListDTO();
            BeanUtils.copyProperties(islandPageDTO,islandUserListDTO);
            map = islandUserService.mapByUserIdAndIslandIds(islandUserListDTO);
            if(islandPageDTO.getIsIn() != null){
                ArrayList<String> islandIds = new ArrayList<>(map.keySet());
                if(islandPageDTO.getIsIn()){
                    lambdaQuery.in(IslandDO::getId,islandIds);
                }else{
                    lambdaQuery.notIn(IslandDO::getId,islandIds);
                }
            }
        }
        Page<IslandDO> page = lambdaQuery.page(new Page<>(islandPageDTO.getPageNow(), islandPageDTO.getPageSize()));
        List<IslandListVO> islandListVOS = IslandDO.DOListToVOList(page.getRecords(),map);
        return new PageResult<>(page.getPages(),islandListVOS);
    }

    public PageResult<IslandEvaluationListVO> pageEvaluation(IslandEvaluationReqListDTO listDTO) {
        LambdaQueryChainWrapper<IslandUserDO> wrapper = islandUserDao.lambdaQuery().select(
                IslandUserDO::getUserId,
                IslandUserDO::getGmtModified,
                IslandUserDO::getComment
        ).eq(IslandUserDO::getIslandId, listDTO.getIslandId());

        Page<IslandUserDO> pageResult = wrapper.page(new Page<>(listDTO.getPageNow(), listDTO.getPageSize()));

        if(pageResult.getRecords().size() == 0){
            return new PageResult<>();
        }

        List<String> userIds = new ArrayList<>();
        for (IslandUserDO record : pageResult.getRecords()) {
            userIds.add(record.getUserId());
        }

        Map<String, UserInfoDTO> userInfoDTOMap = userService.userIdsToUserInfoDTOs(userIds);

        List<IslandEvaluationListVO> evaluationListVOS = new ArrayList<>();
        for (IslandUserDO record : pageResult.getRecords()) {
            evaluationListVOS.add(IslandEvaluationListVO.builder()
                    .content(record.getComment())
                    .nickname(userInfoDTOMap.get(record.getUserId()).getNickname())
                    .avatar(userInfoDTOMap.get(record.getUserId()).getAvatar())
                    .gmtCreate(record.getGmtModified()).build());
        }

        return new PageResult<>(pageResult.getTotal(), evaluationListVOS);
    }

    public PageResult<IslandPageListVO> pageManageList(IslandPageQueryDTO islandQuery) {
        LambdaQueryChainWrapper<IslandDO> query = islandDao.lambdaQuery();

        Optional.of(islandQuery).map(IslandPageQueryDTO::getName).ifPresent(name -> {
            query.likeRight(IslandDO::getName, name);
        });

        Optional.of(islandQuery).map(IslandPageQueryDTO::getUserId).ifPresent(userId -> {
            query.likeRight(IslandDO::getUserId, userId);
        });

        Optional.of(islandQuery).map(IslandPageQueryDTO::getType).ifPresent(type -> {
            query.eq(IslandDO::getType, type);
        });


        Page<IslandDO> pageResult = query.page(new Page<>(islandQuery.getPageNow(), islandQuery.getPageSize()));

        ArrayList<IslandPageListVO> islandDTOS = new ArrayList<>();
        for (IslandDO record : pageResult.getRecords()) {
            IslandPageListVO islandPageListVO = new IslandPageListVO();
            BeanUtils.copyProperties(record, islandPageListVO);
            islandPageListVO.setType(record.getType().getType());
            UserDO userDO = userService.getOne(new QueryWrapper<UserDO>().eq("id", record.getUserId()));
            if (null != userDO) {
                if (StringUtils.isNotBlank(userDO.getNickname())) {
                    islandPageListVO.setNickname(userDO.getNickname());
                }
                if (StringUtils.isNotBlank(userDO.getTel())) {
                    islandPageListVO.setTel(userDO.getTel());
                }
            }
            islandDTOS.add(islandPageListVO);
        }

        return new PageResult<>(pageResult.getTotal(), islandDTOS);

    }
}

